/**
* AutoSWF - Cody Cushing. March 26, 2009
* Copyright (c) 2009 Cody Cushing
* No use restrictions. Maintain this notice in all versions. 
**/

package com.autoswf.lattice
{
	import flexunit.framework.TestCase;
	
	
	public class LatticeTest extends TestCase
	{
		private var lattice:Lattice = new Lattice();
		private var mockLattice1:Lattice = new Lattice();
		private var mockLattice2:Lattice = new Lattice();
		
		private var closureWasInvoked:Boolean;
		private var closure:Function = function():void
		{
			closureWasInvoked = true;
		}
		private var command:Command = new Command();
		private var arr:Array = [];
		
		
		/** Lattice invokes a closure when it is executed. */
		public function testOnExecute01():void
		{
			lattice.onExecute(closure).execute();
			assertTrue(closureWasInvoked);
		}
		
		/** Lattice invokes a command when it is executed. */
		public function testOnExecute02():void
		{
			lattice.onExecute(command).execute();
			assertTrue(command.wasInvoked);
		}
		
		/** Complete results in execute called on next node. */
		public function testExecute01():void
		{
			lattice.addNext(mockLattice1);
			
			lattice.onExecute(closure).execute();
			assertTrue(mockLattice1.hasCompleted);
		}
		
		/** Complete results in execute called on multiple next nodes. */
		public function testExecute02():void
		{
			lattice.addNext(mockLattice1);
			lattice.addNext(mockLattice2);
			
			lattice.onExecute(closure).execute();
			assertTrue(mockLattice1.hasCompleted && mockLattice2.hasCompleted);
		}
		
		/** Multiple nodes must complete before union node is executed. */
		public function testExecute03():void
		{
			mockLattice1.join(lattice);
			mockLattice2.join(lattice);
			
			lattice.onExecute(closure);
			
			mockLattice1.execute();
			assertFalse(closureWasInvoked);

			mockLattice2.execute();
			assertTrue(closureWasInvoked);
		}
		
		/** Synchronous chain executes in order */
		public function testExecute04():void
		{
			var start:Lattice = new Lattice().onExecute(arr.push, "a");
			var middle:Lattice = new Lattice().onExecute(arr.push, "b");
			var end:Lattice = new Lattice().onExecute(arr.push, "c");

			start.join(middle).join(end);

			start.execute();
			
			assertMatch(/a,b,c/, arr);
		}
		
		/** Test concurrent branch of synchronous chains */
		public function testExecute05():void
		{
			var start:Lattice = new Lattice().onExecute(arr.push, "a");
			var branch1:Lattice = start.createAndJoin().onExecute(arr.push, "b");
			var branch2:Lattice = branch1.createAndJoin().onExecute(arr.push, "c");

			start.execute();
			
			assertMatch(/a,b,c|a,c,b/, arr);
		}

		/** Union node is executed after 2 branches reconnect. */
		public function testExecute06():void
		{
			var start:Lattice = new Lattice().onExecute(arr.push, "start");
			var branch1:Lattice = new Lattice().onExecute(arr.push, "branch1");
			var branch2:Lattice = new Lattice().onExecute(arr.push, "branch2");
			var end:Lattice = new Lattice().onExecute(arr.push, "end");
			
			start.join(branch1).join(end);
			start.join(branch2).join(end);

			start.execute();
			
			assertMatch(/start,branch1,branch2,end/, arr);
		}
		
	}
}


internal class Command
{
	public var wasInvoked:Boolean;
	
	public function Command()
	{}
	
	public function execute():void
	{
		wasInvoked = true;
	}
}

